﻿using Simple.Tools.Entity;
using Simple.Tools.Extensions;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

/*********************************************************
 * 命名空间 Simple.Tools.Map
 * 接口名称 BaseCheckType
 * 开发人员：ADMIN
 * 创建时间：2024/1/6 10:48:06
 * 描述说明：
 * 更改历史：
 * 
 * *******************************************************/
namespace Simple.Tools
{
	/// <summary>
	/// 
	/// </summary>
	public abstract class BaseCheckType
	{
		/// <summary>
		/// 
		/// </summary>
		protected Type type;
		/// <summary>
		/// 
		/// </summary>
		protected Type nullableType;
		/// <summary>
		/// 
		/// </summary>
		protected BaseCheckType next;
		/// <summary>
		/// 
		/// </summary>
		/// <param name="type"></param>
		public BaseCheckType(Type type)
		{
			this.type = type;
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="type"></param>
		/// <param name="next"></param>
		public BaseCheckType(Type type, BaseCheckType next)
		{
			this.type = type;
			this.next = next;
		}


		/// <summary>
		/// 
		/// </summary>
		/// <param name="source"></param>
		/// <param name="member"></param>
		/// <returns></returns>
		public virtual bool IsNull(object source, PropertyInfo member)
		{
			if (PropertyEqualsType(member))
			{
				object obj = member.GetValue(source);
				var typeenum = obj.GetType();
				int i = (int)(obj);
				if (SimpleCheck.IsNull(obj))
				{
					return true;
				}
				return Verify(obj.ToByte());
			}

			if (next != null)
			{
				return next.IsNull(source, member);
			}
			if (member.PropertyType.IsClass)
			{
				return false;
			}
			return true;
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="source"></param>
		/// <param name="member"></param>
		/// <returns></returns>
		public virtual bool IsNull(object source, FieldInfo member)
		{
			if (next != null)
			{
				return next.IsNull(source, member);
			}
			if (member.FieldType.IsClass)
			{
				return false;
			}
			return true;
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="map"></param>
		/// <param name="pSource"></param>
		/// <param name="pTarget"></param>
		/// <param name="sourceValue"></param>
		/// <param name="Target"></param>
		public virtual void SetValue(MapToAttribute map, PropertyInfo pSource, PropertyInfo pTarget, object sourceValue, object Target)
		{
			if (SimpleCheck.IsNull(map.TargetType))
			{
				map.TargetType = pTarget.PropertyType;
			}

		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="map"></param>
		/// <param name="pSource"></param>
		/// <param name="pTarget"></param>
		public virtual void SetValue(MapToAttribute map, Type pSource, Type pTarget, object sourceValue)
		{
			if (SimpleCheck.IsNull(map.TargetType))
			{
				map.TargetType = pTarget;
			}

		}

		public virtual object GetTargetValue(MapToAttribute map, Type pSource, Type pTarget, object sourceValue)
		{
			return null;
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="map"></param>
		/// <param name="pSource"></param>
		/// <param name="pTarget"></param>
		/// <param name="sourceValue"></param>
		/// <param name="Target"></param>
		public virtual void SetValue(MapToAttribute map, FieldInfo pSource, FieldInfo pTarget, object sourceValue, object Target)
		{
			if (SimpleCheck.IsNull(map.TargetType))
			{
				map.TargetType = pTarget.FieldType;
			}
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="property"></param>
		/// <param name="value"></param>
		/// <param name="target"></param>
		public virtual void SetValue(PropertyInfo property, object value, object target)
		{

		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="fieldinfo"></param>
		/// <param name="value"></param>
		/// <param name="target"></param>
		public virtual void SetValue(FieldInfo fieldinfo, object value, object target)
		{

		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="value"></param>
		/// <param name="prop"></param>
		/// <param name="max"></param>
		/// <param name="min"></param>
		/// <returns></returns>
		public virtual KeyValue<bool, string> VerifyRange(object value, PropertyInfo prop, double max, double min)
		{
			if (next != null)
			{
				return next.VerifyRange(value, prop, max, min);
			}
			return new KeyValue<bool, string>() { Key = true, Value = string.Empty };
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="prop"></param>
		/// <returns></returns>
		protected bool PropertyEqualsType(PropertyInfo prop)
		{
			if (prop == null)
			{
				return false;
			}

			var result = prop.PropertyType == type || prop.PropertyType == nullableType ||
				(prop.PropertyType.BaseType == nullableType && nullableType == typeof(Enum));

			if (!result)
			{
				if (typeof(Nullable<>).Name == prop.PropertyType.Name)
				{
					if (!SimpleCheck.IsNullOrEmpty(prop.PropertyType.GenericTypeArguments))
					{
						result = prop.PropertyType.GenericTypeArguments[0].BaseType == nullableType;
					}
				}
				else if (typeof(Nullable<>).Name == prop.PropertyType.BaseType.Name)
				{
					//result = prop.PropertyType.BaseType == nullableType;
				}
			}
			return result;
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="targetType"></param>
		/// <returns></returns>
		protected bool EqualsType(Type targetType)
		{
			if (targetType == null)
			{
				return false;
			}

			var result = targetType == type || targetType == nullableType
				|| (type == typeof(Enum) && targetType.BaseType == nullableType);
			if (!result)
			{
				if (typeof(Nullable<>).Name == targetType.Name)
				{
					if (!SimpleCheck.IsNullOrEmpty(targetType.GenericTypeArguments))
					{
						result = targetType.GenericTypeArguments[0].BaseType == nullableType;
					}
				}
			}
			return result;
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="field"></param>
		/// <returns></returns>
		protected bool FieldEqualsType(FieldInfo field)
		{
			if (field == null)
			{
				return false;
			}

			var result = field.FieldType == type || field.FieldType == nullableType
				|| (field.FieldType == nullableType && nullableType == typeof(Enum));

			if (!result)
			{
				if (typeof(Nullable<>).Name == field.FieldType.Name)
				{
					if (!SimpleCheck.IsNullOrEmpty(field.FieldType.GenericTypeArguments))
					{
						result = field.FieldType.GenericTypeArguments[0].BaseType == nullableType;
					}
				}
			}
			return result;
		}
		/// <summary>
		/// 
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="value"></param>
		/// <returns></returns>
		public virtual bool Verify<T>(T value)
		{
			return false;
		}
	}
}
